home *** CD-ROM | disk | FTP | other *** search
- Path: uni-erlangen.de!winx03!sunshine!schoof
- From: schoof@informatik.uni-wuerzburg.de (Jochen Schoof)
- Newsgroups: comp.lang.c
- Subject: Re: Tough FACTORIAL math problem...
- Followup-To: comp.lang.c
- Date: 15 Feb 1996 10:16:54 GMT
- Organization: University of Wuerzburg, Germany
- Message-ID: <4fv16m$cuj@winx03.informatik.uni-wuerzburg.de>
- References: <4fr8be$ass@news.iconn.net> <31224679.6193@born.com>
- NNTP-Posting-Host: wi2x01.informatik.uni-wuerzburg.de
- X-Newsreader: TIN [version 1.2 PL2]
-
- John Cleland (clelaj@born.com) wrote:
- : The Crow wrote:
- : >
- : > Here is what I am trying to do, I want to find the last NON-ZERO digit of a
- : > given factorial. For instance,
- : >
- : > 5! = 120
- : >
- : > so the last non-zero digit is 2. I want to be able to do this up to 1000.
- : > Problem is, no matter how huge of a data-type you use, there isn't any way
- : > for
- : > the computer to handle 1000!, it is however possible to find the last
- : > non-zero
- : > digit somehow. One thing I have tried is as I went through mulitplying the
- : > series of numbers in the factorial (5 * 4 * 3 * 2) I would remove all the
- : > trailing ZEROS, I got this to work up to 789, but it wont work with 1000
- : > and i
- : > am not really sure why. If anyone has a clue how I can do this let me know.
-
- You might want to use a library that provides arbitrary length precision
- when in need of computations like 1000! The computer can really do a lot
- if only you provide the right programs :-)
-
- : Don't just strip the trailing zeros, remove all digits except the last
- : non-zero
- : digit (which is your output) and then multiply by the next number in
- : your sequence.
- : This keeps the numbers down to a managable level and gives the correct
- : answer as
- : no more significant digit can affect the value of the LSD.
- :
- : If we have a function int LSD(int val) which computes the value of the least
- : significant non-zero digit the pseudo C code should be something like :
- :
- : int factLSD = 1;
- : int i;
- :
- : for (i = 1; i <= 1000; i++)
- : {
- : factLSD = LSD(i * factLSD);
- : print i, factLSD;
- : }
-
- Sorry, but this technique does NOT work as can be proven easily:
-
- 14! equals 87178291200 which results in its LSD being 2
-
- The function above (after being ported to legal C) tells us the LSD
- of 15! must be 3, but in fact
-
- 15! equals 1307674368000 which results in its LSD being 8
-
- in contradiction to what your function said. It is not sufficient
- to only keep track of the very last relevant digit. The problem
- mentioned above can be avoided when storing the last two relevant
- digits and I believe this technique finally is sufficient and
- still alows to compute the digits for faculties far beyond 1000.
- Thus the following function should work as desired:
-
- int factorial_lsd(int n)
- {
- int result=1, i;
-
- if(n>1)
- for(i=1;i<=n;i++)
- {
- result*=i;
- while(result%10==0) result/=10;
- result%=100;
- }
- return temp%10;
- }
-
- Hope this helps...
-
- - Jochen
-
- PS: I did not provide my little mathematical analysis of the
- required multiplications, because they are a little boring.
-
- --
- --------------------------------------------------------------------------
- Jochen Schoof mailto:schoof@informatik.uni-wuerzburg.de
- Lehrstuhl fuer Informatik II +-------------------------------------------
- Universitaet Wuerzburg | You are just reading a .sig-light:
- D-97074 Wuerzburg (Germany) | It is free of fat, sugar and cholesterol!
- ------------------------------+-------------------------------------------
- WWW-Homepage: http://www.informatik.uni-wuerzburg.de/staff/joscho
- --------------------------------------------------------------------------
-